package com.winit.openapi.ums.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winit.common.spi.SPIException;
import com.winit.common.spi.context.CommandContext;
import com.winit.erp.spi.bpartner.BpartnerService;
import com.winit.erp.spi.bpartner.command.BpartnerCommand;
import com.winit.erp.spi.bpartner.vo.Bpartner;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.FastJSONUtils;
import com.winit.openapi.util.ValidateUtil;
import com.winit.ums.spi.finance.ApplicationService;
import com.winit.ums.spi.finance.FinanceContractService;
import com.winit.ums.spi.finance.command.CreateBankAccountCommand;
import com.winit.ums.spi.finance.command.CreateCompanyInfoCommand;
import com.winit.ums.spi.finance.command.CreateCreditInfoCommand;
import com.winit.ums.spi.finance.command.CreateFinancialContractCommand;
import com.winit.ums.spi.finance.command.FinanceContactCommand;
import com.winit.ums.spi.finance.command.FinanceContactListCommand;
import com.winit.ums.spi.finance.command.ModifyFinanceBaseInfoCommand;
import com.winit.ums.spi.finance.command.ModifyRegisterInfoCommand;
import com.winit.ums.spi.finance.command.QueryContractProgressCommand;
import com.winit.ums.spi.finance.command.QueryFinanceBaseInfoCommand;
import com.winit.ums.spi.finance.command.SellPlatformInfoCommand;
import com.winit.ums.spi.finance.vo.FinanceBaseInfoVo;
import com.winit.ums.spi.finance.vo.FinanceContractProgressVo;

/**
 * 金融产品基础信息接口
 * 
 * @version
 * 
 * <pre>
 * Author   Version     Date        Changes
 * jun.lu   1.0         2016年5月12日  Created
 * </pre>
 * 
 * @since 1.
 */
@Controller
@RequestMapping(value = "/ums/finance")
public class FinanceContractController extends BaseController {

    private static Logger          logger = LoggerFactory.getLogger(FinanceContractController.class);
    @Resource
    private FinanceContractService financeContractService;

    @Resource
    private BpartnerService        bpartnerService;
    @Resource
    private ApplicationService     applicationService;

    /**
     * 大查询：查询所有的基本信息
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/queryCompanyInfo")
    public String queryCompanyInfo(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        QueryFinanceBaseInfoCommand financeBaseInfoCommand = FastJSONUtils.toJavaObject(requestMsg.getData(),
            QueryFinanceBaseInfoCommand.class);

        if (financeBaseInfoCommand == null) {
            financeBaseInfoCommand = new QueryFinanceBaseInfoCommand();
        }
        String userId = CommandContext.getContext().getUserId();
        BpartnerCommand bpartnerCommand = new BpartnerCommand();
        bpartnerCommand.setcBpartnerId(Long.valueOf(userId));
        Bpartner bpartner = bpartnerService.queryBpartnerById(bpartnerCommand);
        if (bpartner == null) {
            logger.info("根据客户id:{}查询客户code为空", userId);
            return ERROR;
        }
        financeBaseInfoCommand.setCustomerCode(bpartner.getValue());
        financeBaseInfoCommand.setCtx(CommandContext.getContext());

        FinanceBaseInfoVo financeBaseInfoVo = financeContractService.queryFinanceBaseInfo(financeBaseInfoCommand);
        responseMsg.setData(financeBaseInfoVo);
        return SUCCESS;
    }

    /**
     * 注册信息修改
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/modifyRegisterInfo")
    public String modifyRegisterInfo(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        ModifyRegisterInfoCommand registerCommand = FastJSONUtils.toJavaObject(requestMsg.getData(),
            ModifyRegisterInfoCommand.class);
        registerCommand.setCustomerCode(getCustomerCode());
        registerCommand.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.modifyRegisterInfo(registerCommand);
        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 第一步,修改公司信息
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/saveCompanyInfo")
    public String saveCompanyInfo(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        // 校验图片
        validatePic(requestMsg.getData(), "businessLicenseList");
        validatePic(requestMsg.getData(), "taxLicenseList");

        // 校验参数
        validateParams(requestMsg.getData(), true);

        CreateCompanyInfoCommand companyInfoCommand = FastJSONUtils.toJavaObject(requestMsg.getData(),
            CreateCompanyInfoCommand.class);
        companyInfoCommand.setCustomerCode(getCustomerCode());
        companyInfoCommand.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.createOrModifyCompanyInfo(companyInfoCommand);
        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 第二步,保存银行数据
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/saveBankInfo")
    public String saveBankInfo(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        // 校验参数
        validateParams(requestMsg.getData(), true);
        // 设置上下文
        CreateBankAccountCommand bankAccountCommand = FastJSONUtils.toJavaObject(requestMsg.getData(),
            CreateBankAccountCommand.class);
        bankAccountCommand.setCustomerCode(getCustomerCode());
        bankAccountCommand.setCtx(CommandContext.getContext());
        // 保存数据
        Integer retValue = financeContractService.createOrModifyBankInfo(bankAccountCommand);
        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 第三步,联系人信息
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/saveContact")
    public String saveContact(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验参数
        validateParams(params, true);

        List<FinanceContactCommand> commandList = FastJSONUtils.getObjectList(params,
            FinanceContactCommand.class,
            "contactList");
        String customerCode = getCustomerCode();
        for (FinanceContactCommand command : commandList) {
            command.setCustomerCode(customerCode);
            command.setCtx(CommandContext.getContext());
        }
        Integer retValue = financeContractService.createOrModifyContact(commandList);

        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 第四步,保存销售平台数据
     */
    @RequestMapping(value = "/saveSellerPlatform")
    public String saveSellerPlatform(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验参数
        validateSellplat(params);

        SellPlatformInfoCommand command = FastJSONUtils.toJavaObject(params, SellPlatformInfoCommand.class);
        String customerCode = getCustomerCode();
        command.setCustomerCode(customerCode);
        command.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.createOrModifySellPlatformInfo(command);

        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 第五步骤,保存资信情况
     */
    @RequestMapping(value = "/saveCreditInfo")
    public String saveCreditInfo(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验图片
        validatePic(params, "taxPic");
        validatePic(params, "cardPic");

        // 校验参数
        validateParams(params, true);
        // 资信记录
        CreateCreditInfoCommand command = FastJSONUtils.toJavaObject(params, CreateCreditInfoCommand.class);
        String customerCode = getCustomerCode();
        command.setCustomerCode(customerCode);
        command.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.createOrModifyCreditInfo(command);

        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 第六步,提交服务申请接口
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/submit")
    public String financeSubmit(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验参数
        validateParams(params, true);
        // 提交服务
        CreateFinancialContractCommand command = FastJSONUtils.toJavaObject(params,
            CreateFinancialContractCommand.class);
        String customerCode = getCustomerCode();
        command.setCustomerCode(customerCode);
        command.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.createFinaceContract(command);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("day", retValue);
        responseMsg.setData(map);
        return SUCCESS;
    }

    /**
     * 第七步,查询服务申请进度接口
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/queryApplicationProgress")
    public String queryApplicationProgress(@ModelAttribute RequestMsg requestMsg,
                                           @ModelAttribute ResponseMsg responseMsg) {
        // 查询申请进度
        QueryContractProgressCommand contractCommand = new QueryContractProgressCommand();
        String customerCode = getCustomerCode();
        contractCommand.setCustomerCode(customerCode);
        contractCommand.setCtx(CommandContext.getContext());
        FinanceContractProgressVo retValue = financeContractService.queryFinanceContractProgress(contractCommand);

        responseMsg.setData(retValue);
        return SUCCESS;
    }

    @RequestMapping(value = "/modifyAllCompanyBaseInfo")
    public String modifyAllCompanyBaseInfo(@ModelAttribute RequestMsg requestMsg,
                                           @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验参数
        validateParams(params, true);
        // 校验图片
        validatePic(params, "businessLicenseList");
        validatePic(params, "taxLicenseList");
        validatePic(params, "taxPic");
        validatePic(params, "cardPic");

        ModifyFinanceBaseInfoCommand command = FastJSONUtils.toJavaObject(params, ModifyFinanceBaseInfoCommand.class);
        String customerCode = getCustomerCode();
        command.setCustomerCode(customerCode);
        command.setCtx(CommandContext.getContext());
        if (command.getContactList() != null && command.getContactList().size() > 0) {
            for (FinanceContactCommand fcommand : command.getContactList()) {
                fcommand.setCustomerCode(customerCode);
                fcommand.setCtx(CommandContext.getContext());
            }
        }
        String result = applicationService.queryApplicationNewDataToOldData(command);
        logger.info("提交修改资料，校验返回的数据为："+result);
        if(result ==null || "".equals(result)){
            throw new SPIException(ErrorCode.CUSTOMER_INFO_NULL_MODIFY);
        }
        Integer retValue = financeContractService.modifyFullFinanceBaseInfo(command);
        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 根据上下文获取客户编码
     * 
     * @return
     */
    private String getCustomerCode() {
        String userId = CommandContext.getContext().getUserId();
        BpartnerCommand bpartnerCommand = new BpartnerCommand();
        bpartnerCommand.setcBpartnerId(Long.valueOf(userId));
        Bpartner bpartner = bpartnerService.queryBpartnerById(bpartnerCommand);
        if (bpartner == null) {
            throw new SPIException(ErrorCode.CUSTOMER_CODE_IS_NULL);
        }
        return bpartner.getValue();
    }

    /**
     * 销售平台添加校验
     * 
     * @param obj
     */
    private void validateSellplat(Object obj) {
        JSONObject jsons = JSON.parseObject(obj.toString());
        JSONArray productInfo = jsons.getJSONArray("sellProductList");
        for (Object json : productInfo) {
            JSONObject jsonObj = JSON.parseObject(json.toString());
            ValidateUtil.validImportMaxLength(jsonObj, "sellProduct", "产品名称", 255, true);
            ValidateUtil.validImportMaxLength(jsonObj, "sellPeriod", "销售期间", 50, true);
            ValidateUtil.validImportMaxLength(jsonObj, "productPeekTime", "产品淡旺季", 50, true);
            if (jsonObj.getString("sellProduct") != null) {
                if (!jsonObj.getString("sellProduct").matches("[^@#￥$%&(){}<>]{0,}")) {
                    throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "产品名称");
                }
            }
            if (jsonObj.getString("sellPeriod") != null) {
                if (!jsonObj.getString("sellPeriod").matches("[^@#￥$%&(){}<>]{0,}")) {
                    throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "销售期间");
                }
            }
            if (jsonObj.getString("productPeekTime") != null) {
                if (!jsonObj.getString("productPeekTime").matches("[^@#￥$%&(){}<>]{0,}")) {
                    throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "产品淡旺季");
                }
            }
        }
        JSONArray productSales = jsons.getJSONArray("sellPlatformList");

        for (Object json : productSales) {
            JSONObject jsonObj = JSON.parseObject(json.toString());
            ValidateUtil.validImportMaxLength(jsonObj, "sellPlatform", "销售平台", 100, true);
            ValidateUtil.validImportMaxLength(jsonObj, "sellCountry", "销售国家", 64, true);
            ValidateUtil.validImportMaxLength(jsonObj, "turnoverQuarter", "三个月销售额", 14, true);
            ValidateUtil.validImportMaxLength(jsonObj, "turnoverYear", "近一年销售额", 14, true);
            if (jsonObj.getString("sellPlatform") != null) {
                if (!jsonObj.getString("sellPlatform").matches("[^@#￥$%&(){}<>]{0,}")) {
                    throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "销售平台");
                }
            }
            if (jsonObj.getString("sellCountry") != null) {
                if (!jsonObj.getString("sellCountry").matches("[^@#￥$%&(){}<>]{0,}")) {
                    throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "销售国家");
                }
            }
        }
        validatePic(jsons, "salesPic");
        validatePic(jsons, "paypalPic");
    }

    /**
     * 图片校验
     * 
     * @param obj
     * @param type
     */
    private void validatePic(Object obj, String type) {
        if (obj == null) {
            return;
        }

        JSONObject jsonObj = JSON.parseObject(obj.toString());
        if (jsonObj == null) {
            return;
        }

        JSONArray pics = jsonObj.getJSONArray(type);
        if (pics == null) {
            return;
        }

        for (Object pic : pics) {
            if (pic != null && pic instanceof String) {
                String picStr = pic.toString();
                String[] picSplit = picStr.split("\\.");
                if (picSplit.length >= 2) {
                    String picTypes = "jpg|jpeg|png|bmp|gif";
                    if (!picTypes.contains(picSplit[picSplit.length - 1].toLowerCase())) {
                        throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "图片格式不正确！");
                    }
                } else {
                    throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "图片格式不正确！");
                }

            }
        }
    }

    /**
     * 校验添加地址接口参数基本特性
     * 
     * @param json
     */
    private void validateParams(Object obj, boolean checkNull) {
        JSONObject json = JSON.parseObject(obj.toString());
        if (json == null) {
            return;
        }
        ValidateUtil.validImportMaxLength(json, "name", "称呼", 20, checkNull);
        ValidateUtil.validImportMaxLength(json, "position", "职位", 20, checkNull);
        ValidateUtil.validImportMaxLength(json, "phone", "手机", 20, checkNull);
        ValidateUtil.validImportMaxLength(json, "eMail", "邮箱", 100, checkNull);
        ValidateUtil.validImportMaxLength(json, "qq", "QQ", 40, checkNull);
        ValidateUtil.validImportMaxLength(json, "positionType", "职位类型", 10, checkNull);
        ValidateUtil.validImportMaxLength(json, "organizationId", "组织ID", 11, true);

        ValidateUtil.validImportMaxLength(json, "registerNo", "企业登记号", 100, checkNull);
        ValidateUtil.validImportMaxLength(json, "director", "董事", 10, checkNull);

        ValidateUtil.validImportMaxLength(json, "accountNo", "开户行账号", 20, checkNull);
        ValidateUtil.validImportMaxLength(json, "bank", "开户行", 60, checkNull);
        ValidateUtil.validImportMaxLength(json, "swift", "申请公司SWIFT", 50, checkNull);

        ValidateUtil.validImportMaxLength(json, "companyController", "公司实际控制人", 20, checkNull);
        ValidateUtil.validImportMaxLength(json, "controllerCard", "实际控制人身份证号码", 26, checkNull);

        ValidateUtil.validImportMaxLength(json, "urgencyContactName", "紧急联系人姓名", 20, checkNull);
        ValidateUtil.validImportMaxLength(json, "urgencyPhone", "紧急联系人电话", 20, checkNull);
        // 校验是否存在特殊字符
        if (json.getString("name") != null) {
            if (!json.getString("name").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "称呼");
            }
        }
        if (json.getString("registerNo") != null) {
            if (!json.getString("registerNo").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "企业登记号");
            }
        }
        if (json.getString("accountNo") != null) {
            if (!json.getString("accountNo").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "开户行账号");
            }
        }
        if (json.getString("bank") != null) {
            if (!json.getString("bank").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "开户行");
            }
        }
        if (json.getString("swift") != null) {
            if (!json.getString("swift").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "申请公司SWIFT");
            }
        }
        if (json.getString("companyController") != null) {
            if (!json.getString("companyController").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "公司实际控制人");
            }
        }
        if (json.getString("controllerCard") != null) {
            if (!json.getString("controllerCard").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "实际控制人身份证号码");
            }
        }
        if (json.getString("urgencyContactName") != null) {
            if (!json.getString("urgencyContactName").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "紧急联系人姓名");
            }
        }
        if (json.getString("urgencyPhone") != null) {
            if (!json.getString("urgencyPhone").matches("[^@#￥$%&(){}<>]{0,}")) {
                throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "紧急联系人电话");
            }
        }

    }
    
    /**
     * 保存草稿,修改公司信息
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/saveCompanyInfoDraft")
    public String saveCompanyInfoDraft(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {

        // 校验图片
        validatePic(requestMsg.getData(), "businessLicenseList");
        validatePic(requestMsg.getData(), "taxLicenseList");

        // 校验参数
        validateParams(requestMsg.getData(), false);

        CreateCompanyInfoCommand companyInfoCommand = FastJSONUtils.toJavaObject(requestMsg.getData(),
            CreateCompanyInfoCommand.class);
        companyInfoCommand.setCustomerCode(getCustomerCode());
        companyInfoCommand.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.modifyCompanyInfoDraft(companyInfoCommand);
        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 保存草稿,修改银行数据
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/saveBankInfoDraft")
    public String saveBankInfoDraft(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        // 校验参数
        validateParams(requestMsg.getData(), false);
        // 设置上下文
        CreateBankAccountCommand bankAccountCommand = FastJSONUtils.toJavaObject(requestMsg.getData(),
            CreateBankAccountCommand.class);
        bankAccountCommand.setCustomerCode(getCustomerCode());
        bankAccountCommand.setCtx(CommandContext.getContext());
        // 保存数据
        Integer retValue = financeContractService.modifyBankInfoDraft(bankAccountCommand);
        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 保存草稿,修改联系人信息
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/saveContactDraft")
    public String saveContactDraft(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验参数
        validateParams(params, false);

        String customerCode = getCustomerCode();
        FinanceContactListCommand contactListCmd = new FinanceContactListCommand();
        contactListCmd.setCustomerCode(customerCode);
        contactListCmd.setCtx(CommandContext.getContext());
        
        List<FinanceContactCommand> commandList = new ArrayList<FinanceContactCommand>();
        JSONObject jsonObj = JSON.parseObject(params.toString());
        if(jsonObj.containsKey("contactList")){
            JSONArray result = jsonObj.getJSONArray("contactList");
            commandList = JSON.parseArray(result.toJSONString(), FinanceContactCommand.class);
            for (FinanceContactCommand command : commandList) {
                command.setCustomerCode(customerCode);
                command.setCtx(CommandContext.getContext());
            }
        }
        contactListCmd.setContactList(commandList);
        Integer retValue = financeContractService.modifyContactDraft(contactListCmd);

        responseMsg.setData(retValue);
        return SUCCESS;
    }

    /**
     * 保存草稿,修改资信信息
     */
    @RequestMapping(value = "/saveCreditInfoDraft")
    public String saveCreditInfoDraft(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        // 校验图片
        validatePic(params, "taxPic");
        validatePic(params, "cardPic");

        // 校验参数
        validateParams(params, false);
        // 资信记录
        CreateCreditInfoCommand command = FastJSONUtils.toJavaObject(params, CreateCreditInfoCommand.class);
        String customerCode = getCustomerCode();
        command.setCustomerCode(customerCode);
        command.setCtx(CommandContext.getContext());
        Integer retValue = financeContractService.modifyCreditInfoDraft(command);

        responseMsg.setData(retValue);
        return SUCCESS;
    }
    
}
